package com.zyj.rabbitmq.config;

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitConfig {

    /**************************fanout模式参数******************************/
    public static final String EXCHANGE_NAME = "fanout-exchange";
    public static final String FANOUT_A = "fanout.A";
    public static final String FANOUT_B = "fanout.B";
    public static final String FANOUT_C = "fanout.C";


    /**************************topic模式参数******************************/
    public static final String EXCHANGE_NAME_TOPIC = "topic-exchange";
    public static final String TOPIC = "topic";
    public static final String TOPIC_A = "topic.A";
    public static final String TOPIC_B = "topic.B";

    /***************************延迟消费*************************************/
    public static final String QUEUE_NAME = "lazy-queue-t";
    public static final String EXCHANGE_NAME_LAZY = "lazy-exchange-t";

    @Bean
    public Queue Queue() {
        return new Queue("hello");
    }


    /**
     * direct
     * direct模式一般情况下只需要定义queue 使用自带交换机（defaultExchange）无需绑定交换机,适用场景：点对点
     * @return
     */
    @Bean
    public Queue p2pQueue(){
        return new Queue("p2pQueue",true);
    }


    /**
     * fanout则模式需要将多个queue绑定在同一个交换机上
     * 适用场景
     * - 大规模多用户在线（MMO）游戏可以使用它来处理排行榜更新等全局事件
     * - 体育新闻网站可以用它来近乎实时地将比分更新分发给移动客户端
     * - 分发系统使用它来广播各种状态和配置更新
     * - 在群聊的时候，它被用来分发消息给参与群聊的用户
     */
    @Bean
    public Queue AMessage(){
        return  new Queue (FANOUT_A);
    }

    @Bean
    public Queue BMessage(){
        return  new Queue (FANOUT_B);
    }

    @Bean
    public Queue CMessage(){
        return new Queue (FANOUT_C);
    }

    @Bean
    public FanoutExchange fanoutExchange(){
        return new FanoutExchange(EXCHANGE_NAME);
    }

    @Bean
    public Binding bindingExchangeA(Queue AMessage,FanoutExchange fanoutExchange){
        return BindingBuilder.bind(AMessage).to(fanoutExchange);
    }

    @Bean
    public Binding bindingExchangeB(Queue BMessage,FanoutExchange fanoutExchange){
        return BindingBuilder.bind(BMessage).to(fanoutExchange);
    }

    @Bean
    public Binding bindingExchangeC(Queue CMessage,FanoutExchange fanoutExchange){
        return BindingBuilder.bind(CMessage).to(fanoutExchange);
    }


    /**
     * topic
     * 这种模式较为复杂，简单来说，就是每个队列都有其关心的主题，所有的消息都带有一个“标题”，Exchange会将消息转发到所有关注主题能与RouteKey模糊匹配的队列。
     * 在进行绑定时，要提供一个该队列关心的主题，如“topic.# （“#”表示0个或若干个关键字，“*”表示一个关键字。 ）
     * 适用场景
     * - 分发有关于特定地理位置的数据，例如销售点
     * - 由多个工作者（workers）完成的后台任务，每个工作者负责处理某些特定的任务
     * - 股票价格更新（以及其他类型的金融数据更新）
     * - 涉及到分类或者标签的新闻更新（例如，针对特定的运动项目或者队伍）
     * - 云端的不同种类服务的协调
     * - 分布式架构/基于系统的软件封装，其中每个构建者仅能处理一个特定的架构或者系统。
     * 延迟队列
     * 延迟消费：
     *      •如用户生成订单之后，需要过一段时间校验订单的支付状态，如果订单仍未支付则需要及时地关闭订单。
     *      •用户注册成功之后，需要过一段时间比如一周后校验用户的使用情况，如果发现用户活跃度较低，则发送邮件或者短信来提醒用户使用。
     * 延迟重试：
     *      •如消费者从队列里消费消息时失败了，但是想要延迟一段时间后自动重试。
     *      •如果不使用延迟队列，那么我们只能通过一个轮询扫描程序去完成。这种方案既不优雅，也不方便做成统一的服务便于开发人员使用。但是使用延迟队列的话，我们就可以轻而易举地完成。
     * @return
     */
    @Bean
    public Queue queueTopic() {
        return new Queue(RabbitConfig.TOPIC);
    }

    @Bean
    public Queue queueTopicA() {
        return new Queue(RabbitConfig.TOPIC_A);
    }

    @Bean
    public Queue queueTopicB() {
        return new Queue(RabbitConfig.TOPIC_B);
    }

    @Bean
    public TopicExchange exchange() {
        TopicExchange topicExchange = new TopicExchange(EXCHANGE_NAME_TOPIC);
        topicExchange.setDelayed(true);
        return new TopicExchange(EXCHANGE_NAME_TOPIC);
    }

    @Bean
    public Binding bindingExchangeTopic(Queue queueTopic, TopicExchange exchange) {
        return BindingBuilder.bind(queueTopic).to(exchange).with(RabbitConfig.TOPIC);
    }

    @Bean
    public Binding bindingExchangeTopics(Queue queueTopicA, TopicExchange exchange) {
        return BindingBuilder.bind(queueTopicA).to(exchange).with("topic.#");
    }


    /**
     * 延迟消费：
     * •如用户生成订单之后，需要过一段时间校验订单的支付状态，如果订单仍未支付则需要及时地关闭订单。
     * •用户注册成功之后，需要过一段时间比如一周后校验用户的使用情况，如果发现用户活跃度较低，则发送邮件或者短信来提醒用户使用。
     * 延迟重试：
     * •如消费者从队列里消费消息时失败了，但是想要延迟一段时间后自动重试。
     * •如果不使用延迟队列，那么我们只能通过一个轮询扫描程序去完成。这种方案既不优雅，也不方便做成统一的服务便于开发人员使用。但是使用延迟队列的话，我们就可以轻而易举地完成。
     * 设置交换机延迟属性为true
     * @return
     */
//    @Bean
//    public Queue queueLazy() {
//        return new Queue(QUEUE_NAME, true);
//    }
//
//    @Bean
//    public DirectExchange defaultExchange(){
//        DirectExchange directExchange = new DirectExchange(EXCHANGE_NAME_LAZY,true,false);
//        directExchange.setDelayed(true);
//        return directExchange;
//    }
//
//    @Bean
//    public Binding bindingLazy(){
//        return BindingBuilder.bind(queueLazy()).to(defaultExchange()).with(QUEUE_NAME);
//    }











}
